package data;

import org.apache.commons.lang3.ArrayUtils;
import util.ImportFile;
import util.Judge;
import util.RandomGen;

import java.util.Arrays;
import java.util.List;

/*
 * 标记类
 * order:序号
 * name:标记号（流水号）
 * chromosome:探针对应的染色体
 * position:探针位置
 * m_detail:markers其他的一些细节
 *
 * */
public class Markers {
    private int[] order;
    private String[] name;
    private String[] chromosome;
    private int[] position;
    private M_Detail m_detail;

    public int[] getOrder() {
        return order;
    }

    public void setOrder(int[] order) {
        this.order = order;
    }

    public M_Detail getM_detail() {
        return m_detail;
    }

    public void setM_detail(M_Detail m_detail) {
        this.m_detail = m_detail;
    }

    public String[] getName() {
        return name;
    }

    public void setName(String[] name) {
        this.name = name;
    }

    public String[] getChromosome() {
        return chromosome;
    }

    public void setChromosome(String[] chromosome) {
        this.chromosome = chromosome;
    }

    public int[] getPosition() {
        return position;
    }

    public void setPosition(int[] position) {
        this.position = position;
    }

    //markers的一些细节
    public static class M_Detail{
        String basicNumber;
        int chromosomeNumber;
        int totalNumber;
        int posMin;  //用来记录模拟数据中的位点选择区间（只针对仿真数据，对真实数据无用）
        int posMax;
        int[] start; //从0开始
        int[] end;
        int[] probesPerChrom;
        double[][] log_ratio;
    }

    /*
     * 真实数据(将文件取出来的值赋值)
     * filePath:文件路径
     * symbol:分割符
     * col_title:是否具有列名
     *
     * */
    public void assign(String filePath, String symbol, boolean col_title){
        //list:提取的数据（每一个元素是一行数据，未被分割）
        List list = ImportFile.readFile(filePath);

        int row_length = col_title?list.size()-1:list.size();
        int column_length = list.get(0).toString().split(symbol).length;
        String[] lineData = new String[column_length];

        name = new String[row_length];
        chromosome = new String[row_length];
        position = new int[row_length];
        m_detail = new M_Detail();

        for (int i= 0 ;i<row_length;i++){
            if(col_title==false){
                lineData = list.get(i).toString().split(symbol);
            }else {
                lineData = list.get(i+1).toString().split(symbol);
            }
            int j = 0;
            this.name[i] = lineData[j++];
            this.chromosome[i] = lineData[j++];
            this.position[i] = Integer.valueOf(lineData[j]);
        }

        m_detail.chromosomeNumber = Judge.differentType(chromosome);
        m_detail.totalNumber = row_length;
        m_detail.probesPerChrom = get_probesPerChrom(chromosome,m_detail.chromosomeNumber);
        m_detail.start = get_startPoint(chromosome,m_detail.chromosomeNumber);
        m_detail.end = get_endPoint(chromosome,m_detail.chromosomeNumber);
    }

    /*
    * 模拟数据（每种染色体分到的探针数随机，包括实际位置随机）
    * basicNumber:基础流水号
    * chromosomeNumber:染色体数目
    * totalNumber:探针总数
    * posMin/posMax:位点范围(左闭右开，左边0的时候则是开)
    * chromProbeMax:某种染色体的上限探针数
    *
    * */
    public void simulateRandomly(String basicNumber,int chromosomeNumber,int totalNumber,int posMin,int posMax,int chromProbeMax){
        String serial_number; //流水号
        order = new int[totalNumber];
        name = new String[totalNumber];
        chromosome = new String[totalNumber];
        position = new int[totalNumber];
        m_detail = new M_Detail();
        m_detail.basicNumber = basicNumber;
        m_detail.chromosomeNumber = chromosomeNumber;
        m_detail.totalNumber = totalNumber;
        m_detail.posMin = posMin;
        m_detail.posMax = posMax;
        m_detail.start = new int[chromosomeNumber];
        m_detail.end = new int[chromosomeNumber];
        m_detail.probesPerChrom = new int[chromosomeNumber];
        //m_detail.log_ratio = new double[totalNumber];



        if (chromosomeNumber<1 && chromosomeNumber >23){
            System.out.println("染色体数目最多为23对，最少为1对");
        }

        //赋予totalNumber个流水号
        for (int i=0;i<totalNumber;i++){
            order[i] = i+1;
            serial_number = String.valueOf(i+1);
            serial_number = basicNumber.substring(0, basicNumber.length()-serial_number.length())+serial_number; //将序号和流水基础号组合
            name[i] = serial_number;
        }

        //赋予染色体，某个种类的染色体个数随机
        int[] probesPerChrom = new int[chromosomeNumber];
        do {
            probesPerChrom = RandomGen.randomSpliting(chromosomeNumber,totalNumber,chromProbeMax);
        }while (ArrayUtils.contains(probesPerChrom,1) || ArrayUtils.contains(probesPerChrom,2)); //保证每种染色体的标记个数不至于太少
        m_detail.probesPerChrom = probesPerChrom;


        int number = 0;
        int startPoint = 0;
        for (int i=0;i<chromosomeNumber;i++){
            m_detail.start[i] = startPoint;
            m_detail.end[i] = startPoint+probesPerChrom[i]-1;
            startPoint+=probesPerChrom[i];
            for (int j=0;j<probesPerChrom[i];j++){
                if (i!=22){
                    chromosome[number++] = String.valueOf(i+1);
                }else {
                    chromosome[number++] = "X";
                }
            }
        }

        //相应位点赋值
        int[][] positionPerChrom = new int[chromosomeNumber][];

        for (int i=0;i<chromosomeNumber;i++){
            positionPerChrom[i] = new int[probesPerChrom[i]];
            positionPerChrom[i] = RandomGen.randomCommon(posMin,posMax,probesPerChrom[i]);
            Arrays.sort(positionPerChrom[i]);
        }
        number = 0;
        try{
            for (int i=0;i<chromosomeNumber;i++){
                for (int j=0;j<positionPerChrom[i].length;j++){
                    position[number++] = positionPerChrom[i][j];
                }
            }
        }catch(Exception e){
            System.out.println(positionPerChrom[0].length);
            System.out.println(e.toString());
        }

    }


    /*
     * 模拟数据（每种染色体等分探针数，包括实际位置等分）
     * basicNumber:基础流水号
     * chromosomeNumber:染色体数目
     * totalNumber:探针总数
     * posMin/posMax:位点范围(左闭右开，左边0的时候则是开)
     *
     * */
    public void simulateEqually(String basicNumber,int chromosomeNumber,int totalNumber,int posMin,int posMax){
        String serial_number; //流水号
        order = new int[totalNumber];
        name = new String[totalNumber];
        chromosome = new String[totalNumber];
        position = new int[totalNumber];
        m_detail = new M_Detail();
        m_detail.basicNumber = basicNumber;
        m_detail.chromosomeNumber = chromosomeNumber;
        m_detail.totalNumber = totalNumber;
        m_detail.posMin = posMin;
        m_detail.posMax = posMax;
        m_detail.start = new int[chromosomeNumber];
        m_detail.end = new int[chromosomeNumber];
        m_detail.probesPerChrom = new int[chromosomeNumber];


        if (chromosomeNumber<1 && chromosomeNumber >23){
            System.out.println("染色体数目最多为23对，最少为1对");
        }

        if (totalNumber%chromosomeNumber!=0){
            System.out.println("总数" + totalNumber +"无法等分为" + chromosomeNumber + "个");
            return;
        }

        //赋予totalNumber个流水号
        for (int i=0;i<totalNumber;i++){
            order[i] = i+1;
            serial_number = String.valueOf(i+1);
            serial_number = basicNumber.substring(0, basicNumber.length()-serial_number.length())+serial_number; //将序号和流水基础号组合
            name[i] = serial_number;
        }

        //赋予染色体，某个种类的染色体个数随机
        int[] probesPerChrom = new int[chromosomeNumber];

        for (int i=0;i<chromosomeNumber;i++){
            probesPerChrom[i] = totalNumber/chromosomeNumber;
        }


        m_detail.probesPerChrom = probesPerChrom;


        int number = 0;
        int startPoint = 0;
        for (int i=0;i<chromosomeNumber;i++){
            m_detail.start[i] = startPoint;
            m_detail.end[i] = startPoint+probesPerChrom[i]-1;
            startPoint+=probesPerChrom[i];
            for (int j=0;j<probesPerChrom[i];j++){
                if (i!=22){
                    chromosome[number++] = String.valueOf(i+1);
                }else {
                    chromosome[number++] = "X";
                }
            }
        }

        //相应位点赋值
        int[][] positionPerChrom = new int[chromosomeNumber][];

        for (int i=0;i<chromosomeNumber;i++){
            positionPerChrom[i] = new int[probesPerChrom[i]];
            //positionPerChrom[i] = RandomGen.randomCommon(posMin,posMax,probesPerChrom[i]);  //位点实际位置随机分配
            positionPerChrom[i] = RandomGen.equalCommon(posMin,posMax,probesPerChrom[i]);  //位点实际位置等分分配
            Arrays.sort(positionPerChrom[i]);
        }
        number = 0;
        try{
            for (int i=0;i<chromosomeNumber;i++){
                for (int j=0;j<positionPerChrom[i].length;j++){
                    position[number++] = positionPerChrom[i][j];
                }
            }
        }catch(Exception e){
            System.out.println(positionPerChrom[0].length);
            System.out.println(e.toString());
        }

    }


    /*
    * 获得文件中所有染色体对应的探针总数
    * chromosomePerMarker:所有标记对应的染色体
    * chromosomeNumber:该文件中染色体总数
    *
    * */
    private int[] get_probesPerChrom(String[] chromosomePerMarker,int chromosomeNumber){
        int markerNumber = chromosomePerMarker.length;
        int[] probesPerChrom = new int[chromosomeNumber];

        for (int i= 0 ;i<markerNumber;i++){
            if (chromosomePerMarker[i].equals("X")){
                probesPerChrom[22]++;
            }else {
                probesPerChrom[Integer.valueOf(chromosomePerMarker[i])-1]++;
            }
        }

        return probesPerChrom;
    }


    /*
     * 获得文件中所有染色体对应的起始位点
     * chromosomePerMarker:所有标记对应的染色体
     * chromosomeNumber:该文件中染色体总数
     *
     * */
    private int[] get_startPoint(String[] chromosomePerMarker,int chromosomeNumber){
        int markerNumber = chromosomePerMarker.length;
        int[] startPointPerChrom = new int[chromosomeNumber];
        String temp = chromosomePerMarker[0];
        int chrom = 1;

        startPointPerChrom[0] = 0;
        for (int i= 0 ;i<markerNumber;i++){
            //如果不相等
            if (temp.equals(chromosomePerMarker[i])==false){
                startPointPerChrom[chrom++] = i;
                temp = chromosomePerMarker[i];
            }
        }

        return startPointPerChrom;
    }


    /*
     * 获得文件中所有染色体对应的末置位点
     * chromosomePerMarker:所有标记对应的染色体
     * chromosomeNumber:该文件中染色体总数
     *
     * */
    private int[] get_endPoint(String[] chromosomePerMarker,int chromosomeNumber){
        int markerNumber = chromosomePerMarker.length;
        int[] endPointPerChrom = new int[chromosomeNumber];
        String temp = chromosomePerMarker[0];
        int chrom = 0;

        for (int i= 0 ;i<markerNumber;i++){
            //如果不相等
            if (temp.equals(chromosomePerMarker[i])==false){
                endPointPerChrom[chrom] = i-1;
                temp = chromosomePerMarker[i];
            }
        }
        endPointPerChrom[chromosomeNumber-1] = markerNumber-1;

        return endPointPerChrom;
    }
}